<?php

namespace app\index\logic\order;

use app\common\model\order\Charges;
use app\common\ConstVar;
use think\facade\Db;
use app\common\service\DateService;
use app\index\logic\BaseLogic;

/**
 * 船票价格计算器逻辑类
 * 负责处理船票价格的计算逻辑，解耦ShipOrder中的价格计算
 */
class ShipPriceCalculatorLogic extends BaseLogic
{
    private $userInfo;
    private $priceList = [];

    public function __construct(array $userInfo = [])
    {
        $this->userInfo = $userInfo;
    }

    /**
     * 计算指定日期的价格
     * @param string $date 日期
     * @return array
     */
    public function calculate(string $date)
    {
        $charges = $this->getCharges();

        if (empty($charges)) {
            return ['date_type_name' => '', 'price' => 0];
        }

        $this->buildPriceList($charges);

        return $this->getPriceForDate($date);
    }

    /**
     * 获取价格配置
     * @return array
     */
    private function getCharges()
    {
        $ChargesModel = new Charges();
        return $ChargesModel->where(['order_type' => ConstVar::$order_type['ship_order']])->select()->toArray();
    }

    /**
     * 构建价格列表
     * @param array $charges 价格配置数组
     */
    private function buildPriceList(array $charges)
    {
        foreach ($charges as $charge) {
            if ($charge['date_type'] == 1) { // 淡季
                $this->addOffSeasonPrice($charge);
            } else { // 旺季
                $this->addPeakSeasonPrice($charge);
            }
        }
    }

    /**
     * 添加淡季价格
     * @param array $charge 价格配置
     */
    private function addOffSeasonPrice(array $charge)
    {
        $price = $this->getVipPrice($charge);

        $this->priceList['off_season'] = [
            'price' => $price,
            'date_type' => 1,
            'date_type_name' => '淡季'
        ];
    }

    /**
     * 添加旺季价格
     * @param array $charge 价格配置
     */
    private function addPeakSeasonPrice(array $charge)
    {
        if (empty($charge['prices'])) {
            return;
        }

        $prices = json_decode($charge['prices'], true);
        foreach ($prices as $price) {
            if ($price['status'] == 2) { // 禁售
                $price['price'] = 0;
            }

            $this->processPriceRange($price, $charge['date_type']);
        }
    }

    /**
     * 处理价格范围
     * @param array $price 价格信息
     * @param int $dateType 日期类型
     */
    private function processPriceRange(array $price, int $dateType)
    {
        $normalizedPrice = $this->normalizePrice($price, $dateType);

        if (!empty($price['date']) && !empty($price['date_end'])) {
            $this->addDateRangePrice($normalizedPrice, $price['date'], $price['date_end']);
        } elseif (!empty($price['date'])) {
            $this->priceList[$price['date']] = $normalizedPrice;
        } elseif (!empty($price['date_end'])) {
            $this->priceList[$price['date_end']] = $normalizedPrice;
        }
    }

    /**
     * 标准化价格数据
     * @param array $price 原始价格数据
     * @param int $dateType 日期类型
     * @return array
     */
    private function normalizePrice(array $price, int $dateType)
    {
        return [
            'price' => $price['price'],
            'price1' => isset($price['price1']) ? $price['price1'] : $price['price'],
            'price2' => isset($price['price2']) ? $price['price2'] : $price['price'],
            'date_type' => $dateType,
            'date_type_name' => isset(ConstVar::$dataType[$dateType]) ? ConstVar::$dataType[$dateType] : ''
        ];
    }

    /**
     * 添加日期范围价格
     * @param array $price 价格信息
     * @param string $startDate 开始日期
     * @param string $endDate 结束日期
     */
    private function addDateRangePrice(array $price, string $startDate, string $endDate)
    {
        $start = intval(str_replace('-', '', $startDate));
        $end = intval(str_replace('-', '', $endDate));

        if ($start === $end) {
            $this->priceList[$startDate] = $price;
        } elseif ($end > $start) {
            $this->addDateRange($price, $startDate, $endDate);
        }
    }

    /**
     * 添加日期范围内的所有日期
     * @param array $price 价格信息
     * @param string $startDate 开始日期
     * @param string $endDate 结束日期
     */
    private function addDateRange(array $price, string $startDate, string $endDate)
    {
        $dateService = new DateService();
        $days = array_column($dateService->getDateRangeByInterval($startDate, $endDate), 'name');

        foreach ($days as $day) {
            $this->priceList[$day] = $price;
        }
    }

    /**
     * 获取指定日期的价格
     * @param string $date 日期
     * @return array
     */
    private function getPriceForDate(string $date)
    {
        // 先检查具体日期
        if (isset($this->priceList[$date])) {
            $price = $this->priceList[$date];
            return $this->applyVipDiscount($price);
        }

        // 检查淡季价格
        if (isset($this->priceList['off_season'])) {
            return $this->applyVipDiscount($this->priceList['off_season']);
        }

        return ['date_type_name' => '', 'price' => 0];
    }

    /**
     * 应用VIP折扣
     * @param array $price 价格信息
     * @return array
     */
    private function applyVipDiscount(array $price)
    {
        $vipLevel = isset($this->userInfo['vip_level']) ? $this->userInfo['vip_level'] : 0;
        $finalPrice = $price['price'];

        switch ($vipLevel) {
            case 2:
                $finalPrice = $price['price1'];
                break;
            case 3:
                $finalPrice = $price['price2'];
                break;
            default:
                $finalPrice = $price['price'];
                break;
        }

        return [
            'date_type_name' => $price['date_type_name'],
            'price' => $finalPrice
        ];
    }

    /**
     * 获取VIP价格
     * @param array $charge 价格配置
     * @return float
     */
    private function getVipPrice(array $charge)
    {
        $vipLevel = isset($this->userInfo['vip_level']) ? $this->userInfo['vip_level'] : 0;

        switch ($vipLevel) {
            case 2:
                return isset($charge['price1']) ? $charge['price1'] : $charge['price'];
            case 3:
                return isset($charge['price2']) ? $charge['price2'] : $charge['price'];
            default:
                return $charge['price'];
        }
    }
}
